package com.github.bitsapling.sapling.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.github.bitsapling.sapling.enums.PrivacyLevel;
import com.github.bitsapling.sapling.exception.MyCustomException;
import com.github.bitsapling.sapling.result.GraceJSONResult;
import com.github.bitsapling.sapling.entity.User;
import com.github.bitsapling.sapling.controller.bo.InvitationRegisterRequestBO;
import com.github.bitsapling.sapling.controller.bo.RegisterRequestBO;
import com.github.bitsapling.sapling.service.AuthenticationService;
import com.github.bitsapling.sapling.service.InvitationService;
import com.github.bitsapling.sapling.service.UserGroupService;
import com.github.bitsapling.sapling.service.UserService;
import com.github.bitsapling.sapling.utils.PasswordHash;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.github.bitsapling.sapling.utils.IPUtil;
import com.github.bitsapling.sapling.result.ResponseStatusEnum;
import com.github.bitsapling.sapling.controller.bo.LoginRequestBO;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;



@RestController    //表示可以被前端调用
@RequestMapping("user")
@Slf4j
public class UserController {
    @Resource
    private UserService userService;

    @Resource
    private HttpServletRequest request;

    @Resource
    private AuthenticationService authenticationService;

    @Resource
    private UserGroupService userGroupService;

    @Resource
    private InvitationService invitationService;

    @PostMapping("login")
    public GraceJSONResult login(@Valid @RequestBody LoginRequestBO login) {
        String ip = IPUtil.getRequestIp(request);
        User user = userService.getUserByUsername(login.getUsername());
        if (user == null) user = userService.getUserByEmail(login.getUsername());
        if (user == null) {
            log.info("IP {} tried to login with not exists username {}.",ip, login.getUsername());
            authenticationService.markUserLoginFail(ip); // Mark fail because it not use authenticate
            authenticationService.checkAccountLoginAttempts(ip);
            return GraceJSONResult.errorCustom(ResponseStatusEnum.USER_NOT_EXIST_ERROR);
        }
        if(!authenticationService.authenticate(user,login.getPassword(),ip)){
            log.info("IP {} tried to login to user {} with bad password.",ip, login.getUsername());
            return GraceJSONResult.errorCustom(ResponseStatusEnum.PASSWORD_ERROR);
        }
        StpUtil.login(user.getId());
        return GraceJSONResult.ok(userService.getUserSessionResponseDTO(user));
    }

    @PostMapping("register")
    @Transactional
    public GraceJSONResult register(@Valid @RequestBody RegisterRequestBO register) {
        User user = userService.getUserByUsername(register.getUsername());
        if (user != null) {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.USERNAME_EXIST_ERROR);
        }
        user = userService.getUserByEmail(register.getEmail());
        if (user != null) {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.EMAIL_EXIST_ERROR);
        }
        user = new User();
        user.setUsername(register.getUsername());
        user.setEmail(register.getEmail());
        user.setPassword(PasswordHash.hash(register.getPassword()));
        user.setPasskey(UUID.randomUUID().toString());
        user.setCreateTime(LocalDateTime.now());
        user.setCustomTitle("新用户");
        //user.setAvatar("http://localhost:9000/bt7274/avatar/default.jpg");
        user.setSignature("这个用户很懒，还没有个性签名");
        user.setLanguage("zh-CN");
        user.setUploadBandwidth("100mbps");
        user.setDownloadBandwidth("100mbps");
        user.setDownloaded(0L);
        user.setUploaded(0L);
        user.setRealDownloaded(0L);
        user.setRealUploaded(0L);
        //user.setIsp(getISPByIP(IPUtil.getRequestIp(request)));
        user.setIsp("未知");
        user.setKarma(BigDecimal.ZERO);
        user.setInviteSlot(0);
        user.setSeedingTime(0L);
        user.setPersonalAccessToken(UUID.randomUUID().toString());
        user.setPrivacyLevel(String.valueOf(PrivacyLevel.LOW));
        user.setGroupId(userGroupService.getDefaultUserGroup().getId());
        user = userService.createOrUpdate(user);
        StpUtil.login(user.getId());
        return GraceJSONResult.ok(userService.getUserSessionResponseDTO(user));
    }

    // 辅助方法：获取 IP 对应的 ISP 信息
    private String getISPByIP(String ip) {
        try {
            // 使用 ip-api.com 查询 IP 信息
            URL url = new URL("http://ip-api.com/json/" + ip + "?fields=isp");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");

            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            reader.close();

            // 解析 JSON 响应
            ObjectMapper objectMapper = new ObjectMapper();
            Map<String, Object> jsonMap = objectMapper.readValue(response.toString(), Map.class);
            return (String) jsonMap.get("isp");
        } catch (Exception e) {
            log.error("Failed to get ISP information for IP {}: {}", ip, e.getMessage());
            return null;
        }
    }

    @PostMapping("logout")
    public GraceJSONResult logout() {
        if (StpUtil.isLogin()) {
            StpUtil.logout();
            return GraceJSONResult.ok("退出成功！");
        } else {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.FAILED);
        }
    }



    @PostMapping("inviteRegister")
    @Transactional
    public GraceJSONResult inviteRegister(@RequestBody InvitationRegisterRequestBO registerRequestBO) {
        // 提取邀请码
        String invitationCode = registerRequestBO.getInvitationCode();
        // 校验邀请码
        boolean isValid = invitationService.validateInvitationCode(invitationCode);
        if (!isValid) {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.INVITATION_CODE_INVALID_ERROR);
        }

        // 检查用户名是否已存在
        User user = userService.getUserByUsername(registerRequestBO.getUsername());
        if (user != null) {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.USERNAME_EXIST_ERROR);
        }

        // 检查邮箱是否已存在
        user = userService.getUserByEmail(registerRequestBO.getEmail());
        if (user != null) {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.EMAIL_EXIST_ERROR);
        }

        // 创建新用户
        user = new User();
        user.setUsername(registerRequestBO.getUsername());
        user.setEmail(registerRequestBO.getEmail());
        user.setPassword(PasswordHash.hash(registerRequestBO.getPassword()));
        user.setPasskey(UUID.randomUUID().toString());
        user.setCreateTime(LocalDateTime.now());
        user.setCustomTitle("新用户");
        //user.setAvatar("http://localhost:9000/bt7274/avatar/default.jpg");
        user.setSignature("这个用户很懒，还没有个性签名");
        user.setLanguage("zh-CN");
        user.setUploadBandwidth("100mbps");
        user.setDownloadBandwidth("100mbps");
        user.setDownloaded(0L);
        user.setUploaded(0L);
        user.setRealDownloaded(0L);
        user.setRealUploaded(0L);
        user.setIsp("未知");
        user.setKarma(BigDecimal.ZERO);
        user.setInviteSlot(0);
        user.setSeedingTime(0L);
        user.setPersonalAccessToken(UUID.randomUUID().toString());
        user.setPrivacyLevel(String.valueOf(PrivacyLevel.LOW));
        user.setGroupId(2L);

        // 保存用户到数据库
        user = userService.createOrUpdate(user);

        // 标记邀请码已使用
        invitationService.markInvitationCodeUsed(invitationCode, registerRequestBO.getUsername());

        // 用户登录
        StpUtil.login(user.getId());

        return GraceJSONResult.ok(userService.getUserSessionResponseDTO(user));
    }


}
